<?php
/**
 * @Description 自動生成control控制層及API文檔
 * @Sonkwl Xiong
 * @Date 2023/03/31 08:48:53
 * @GET 
 * 
 * @POST 
 * 
 * @Response 
 *  
 */
namespace Sonkwl\UsePHP;

use \Sonkwl\UsePHP\jsoner;

class autocontrol{
    //驗證文件存放位置
    private static $path="control";
    //接口定義array
    private static $iarray=array();
    //設置驗證文件存在位置
    public static function SetPath($path){
        self::$path=trim($path,"/");
        return __CLASS__;
    }
    //設置接口定義文件
    public static function SetIarray($arr){
        self::$iarray=$arr;
        return __CLASS__;
    }
    //生成入口驗證文件
    public static function Create(){
        if(count(self::$iarray)==0){
            jsoner::Response(array("res"=>"NG","message"=>"您沒有載入任何的接口文件"));
        }
        //創建control相關目錄
        if(!is_dir(self::$path)){
            //多级目录处理
            $layers=explode("/",self::$path);
            $layer_dir='';
            foreach ($layers as $key => $value) {
                if($key==0){
                    $layer_dir=$value;
                }else{
                    $layer_dir.="/".$value;
                }
                mkdir($layer_dir,0777);
            }
            // mkdir(self::$path,0777);
            mkdir(self::$path."/get",0777);
            mkdir(self::$path."/post",0777);
            mkdir(self::$path."/validate",0777);
        }
        //創建index入口文件
        if(!is_file(self::$path."/index.php")){
            # 不存在创建
            $indexfile=fopen(self::$path."/index.php","w");
            fwrite($indexfile,"<?php\n");
            fwrite($indexfile,"//功能描述:入口處理\n");
            fwrite($indexfile,"//生成時間:".date("Y-m-d H:i:s")."\n");
            fwrite($indexfile,"//载入框架\n");
            fwrite($indexfile,"include \$_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';\n");
            fwrite($indexfile,"use \Sonkwl\UsePHP\autoroute;\n");
            fwrite($indexfile,"use \Sonkwl\UsePHP\jsoner;\n");
            fwrite($indexfile,"use \Sonkwl\UsePHP\mysqler;\n");
            fwrite($indexfile,"use \Sonkwl\UsePHP\autocontrol;\n");
            fwrite($indexfile,"\n");
            fwrite($indexfile,"autocontrol::ValidateRequest();\n");
            fwrite($indexfile,"autoroute::Run();\n");
            fwrite($indexfile,"?>\n");
            fclose($indexfile);
        }
        
        
        //創建get/post/validate文件
        foreach(self::$iarray as $num => $interface){
            # 生成GET
            if($interface["method"]=="GET"){
                $dir=self::$path."/get";
                if(!is_dir($dir)){
                    mkdir($dir,0777);
                }
                if(!is_file($dir."/".$interface["url"].".php")){
                    //已经存在文件
                    $getfile=fopen($dir."/".$interface["url"].".php","w");
                    fwrite($getfile,"<?php\n");
                    fwrite($getfile,"//功能描述:".$interface["desc"]."處理\n");
                    fwrite($getfile,"//生成時間:".date("Y-m-d H:i:s")."\n");
                    fwrite($getfile,"//GET:".implode(",",array_keys($interface["request"]))."\n");
                    fwrite($getfile,"//RES:".implode(",",array_keys($interface["response"]))."\n");
                    fwrite($getfile,"?>\n");
                    fclose($getfile);
                }
            }

            # 生成POST
            if($interface["method"]=="POST"){
                $dir=self::$path."/post";
                if(!is_dir($dir)){
                    mkdir($dir,0777);
                }
                if(!is_file($dir."/".$interface["url"].".php")){
                    //已经存在文件
                    $postfile=fopen($dir."/".$interface["url"].".php","w");
                    fwrite($postfile,"<?php\n");
                    fwrite($postfile,"//功能描述:".$interface["desc"]."處理\n");
                    fwrite($postfile,"//生成時間:".date("Y-m-d H:i:s")."\n");
                    fwrite($postfile,"//POST:".implode(",",array_keys($interface["request"]))."\n");
                    fwrite($postfile,"//RES-JSON:".implode(",",array_keys($interface["response"]))."\n");
                    fwrite($postfile,"?>\n");
                    fclose($postfile);
                }
            }

            # 生成驗證文檔
            $dir=self::$path."/validate";
            if(!is_dir($dir)){
                mkdir($dir,0777);
            }
            $validatefile=fopen($dir."/".strtolower($interface["method"])."-".$interface["url"].".php","w");
            # 寫入文件基本
            fwrite($validatefile,"<?php\n");
            fwrite($validatefile,"//功能描述:".$interface["desc"]."驗證\n");
            fwrite($validatefile,"//方法説明:".$interface["method"]."\n");
            fwrite($validatefile,"//生成時間:".date("Y-m-d H:i:s")."\n");
            fwrite($validatefile,"use \Sonkwl\UsePHP\jsoner;\n");
            # 寫入文件驗證模塊
            // $colcount=0;
            foreach ($interface["request"] as $key => $value) {
                $validateStr=self::WriteValidate($interface["method"],$key,$value);
                fwrite($validatefile,$validateStr);
            }

            fwrite($validatefile,"?>\n");
            fclose($validatefile);
        }
        echo '配置control成功.<hr>';
        return __CLASS__;
    }
    //写入约束
    public static function WriteValidate($method,$key,$value){
        $TtoB='';//top to bottom
        $BtoT='';//bottom to top
        $key_tag='$_'.$method.'["'.$key.'"]';//$_POST["keyname"]
        $must=isset($value["must"])?FALSE:TRUE;
        $filter=isset($value["filter"])?FALSE:TRUE;
        $isArray=$value["type"]=="array"?TRUE:FALSE;
        $desc=$value["desc"];
        $witer="";
        //文件流
        if($value["type"]=="filestream"){
            $key_tag='$_FILES["'.$key.'"]';//$_POST["keyname"]
            $filter=FALSE;
        }
        //必须匹配
        if($must==FALSE){
            //非必须输入
            $TtoB.="if(isset($key_tag)){\n";
            $BtoT.="}\n";
            $witer="    ";//4空格
        }
        //是否是数组
        if($isArray==TRUE){
            $TtoB.=$witer."foreach($key_tag as \$k=>\$v){\n";
            $BtoT.=$witer."}\n";
            $key_tag=$key_tag."[\$k]";//$_POST["keyname"][$k]
            $witer.=$witer."    ";//增加4空格
        }
        //是否定义keyname
        $TtoB.=$witer."if(!isset($key_tag)){\n";
        $TtoB.=$witer."    jsoner::Response(array(\"res\"=>\"NG\",\"message\"=>\" $desc 没有定义\"));\n";
        $TtoB.=$witer."}\n";
        //regex匹配优先，如匹配直接返回
        if(isset($value["regex"])){
            $TtoB.=$witer."if(!preg_match(\"".$value["regex"]."\",$key_tag)){\n";
            $TtoB.=$witer."    jsoner::Response(array(\"res\"=>\"NG\",\"message\"=>\" $desc 的格式不符合规定\"));\n";
            $TtoB.=$witer."}\n";
            return $TtoB.$BtoT."\n";
        }
        //范围处理
        if(isset($value["area"])){
            $TtoB.=$witer."if(!in_array($key_tag,array(\"".implode('","',$value["area"])."\"))){\n";
            $TtoB.=$witer."    jsoner::Response(array(\"res\"=>\"NG\",\"message\"=>\" $desc 的只能在[".implode(',',$value["area"])."]中选择\"));\n";
            $TtoB.=$witer."}\n";
        }
        //长度处理
        if(isset($value["len"])){
            $len=explode(":",$value["len"]);
            $min=$len[0];
            $max=$len[1];
            $TtoB.=$witer."if(strlen($key_tag)<$min && strlen($key_tag)>$max){\n";
            $TtoB.=$witer."    jsoner::Response(array(\"res\"=>\"NG\",\"message\"=>\" $desc 的字数应该在 $min 到 $max 之间\"));\n";
            $TtoB.=$witer."}\n";
        }

        //filter过滤
        if($filter==TRUE){
            $TtoB.=$witer."$key_tag = addslashes($key_tag);\n";
        }
        return $TtoB.$BtoT."\n";
    }

    //驗證入口文件載入
    public static function ValidateRequest(){
        $page="index"; //頁面
        $method=strtolower($_SERVER["REQUEST_METHOD"]); //請求方法
        # 頁面切換
        if(isset($_GET["p"])){
            $page=$_GET["p"];
        }
        #驗證文件
        $file="validate/".$method."-".$page.".php";
        //echo $file;
        if(!is_file($file)){
            jsoner::Response(array("res"=>"NG","message"=>"驗證文件不存在"));
        }
        include_once $file;
    }

    //生成API文檔
    public static function CreateDocs($docname,$baseurl){
        if(count(self::$iarray)==0){
            jsoner::Response(array("res"=>"NG","message"=>"您沒有載入任何的接口文件"));
        }
        $dir="docs";
        if(!is_dir($dir)){
            mkdir($dir,0777);
        }
        $docs=fopen($dir."/".$docname."-api.md","w");
        fwrite($docs,"# ".$docname."\n");
        fwrite($docs,"> BASEURL:".$baseurl."\n\n");
        fwrite($docs,"|版本號|生成時間|創建人|\n");
        fwrite($docs,"|-|-|-|\n");
        fwrite($docs,"|V".date("ymd")."|".date("Y/m/d H:i")."|sonkwl|\n");
        

        $count=0;
        foreach(self::$iarray as $num => $interface){
            $count++;
            fwrite($docs,"## ".$count.".".$interface["desc"]."\n");
            fwrite($docs,"### ".$interface["method"]."\n");
            fwrite($docs,"> /index.php?p=".$interface["url"]."\n");
            fwrite($docs,"### Request\n");
            fwrite($docs,"body\n");
            //request
            fwrite($docs,"|参数名|描述|类型|是否必须|约束|\n");
            fwrite($docs,"|-|-|-|-|-|\n");
            $regex_list='';
            foreach ($interface["request"] as $key => $value) {
                fwrite($docs,"|".$key."|");
                fwrite($docs,$value["desc"]."|");
                fwrite($docs,$value["type"]."|");
                fwrite($docs,(!isset($value["must"])?"是":"否")."|");
                $val_raw='|';
                if(isset($value["len"])){
                    $sub=explode(":",$value["len"]);
                    $val_raw="字数范围".$sub[0]."~".$sub[1]."|";
                }
                if(isset($value["area"])){
                    $val_raw="选择[".implode(",",$value["area"])."]|";
                }
                if(isset($value["regex"])){
                    $val_raw="正则(见清单)|";
                    $regex_list.=$value["desc"].":".$value["regex"]."\n";
                }
                fwrite($docs,$val_raw."\n");
            }
            if($regex_list!=""){
                fwrite($docs,"正则清单\n");
                fwrite($docs,"```php\n");
                fwrite($docs,$regex_list."\n");
                fwrite($docs,"```\n");
            }
            fwrite($docs,"### Response\n");
            fwrite($docs,"json\n");
            fwrite($docs,"```json\n");
            fwrite($docs,"{\n");
            foreach ($interface["response"] as $key => $value){
                //josn处理
                if(isset($value["json"])){
                    fwrite($docs,"    \"".$key."\":".(isset($value["mul"])?"[":"")."{\n");
                    foreach ($value["json"] as $k => $v) {
                        fwrite($docs,"        \"".$k."\":\"".$v."\",\n");
                    }
                    fwrite($docs,"    }".(isset($value["mul"])?"...]":"")."\n");
                    continue;
                }
                fwrite($docs,"    \"".$key."\":\"".$value["type"]."\",\n");
            }
            fwrite($docs,"}\n");
            fwrite($docs,"```\n");
        }

        fclose($docs);
        echo "API文檔生成OK<hr>";
        return __CLASS__;
    }

    //通过目录读取json生成array
    static public function ReadJsonToArray($dirPath){
        if(!is_dir($dirPath)){
            echo $dirPath."目录不存在";
            exit;
        }
        $iArray=array();
        foreach(scandir($dirPath) as $file){
            if($file=="." || $file==".."){
                continue;
            }
            $json=file_get_contents($dirPath."/".$file);
            $json=json_decode($json,true);
            array_push($iArray,$json);
        }
        self::$iarray=$iArray;
        return __CLASS__;
    }
}
?>